﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Psm.Transport;
using Psm.Logging;
using Psm.Container;
using Psm.Session;
using Psm.Configuration;


namespace Psm.Core
{
    public class PsmHost
    {
        private static ILogger logger = Repository.GetInstance<ILogger>();
        public HostConfiguration Configuration {get; private set;}
        private IServerTransport ServerTransport { get; set; }
        private List<PsmSession> clientSessions = new List<PsmSession>();

        public PsmSession[] ClientSessions 
        {
            get
            {
                lock(clientSessions)
                {
                    return clientSessions.ToArray<PsmSession>();
                }
            }
        } 
        
        public PsmHost(HostConfiguration serverConfiguration)
        {
            this.Configuration = serverConfiguration;
            ServerTransport = Container.Repository.GetInstance<IServerTransport>(this.Configuration.Transport.Type, this.Configuration.Transport.Composition);
            ServerTransport.NewClient += new EventHandler<NewClientEventArgs>(NewClientHandler);
        }

        public void Start()
        {
            this.ServerTransport.Start();
        }

        public void Stop()
        {
            this.ServerTransport.Stop();
        }
        
        void NewClientHandler(object sender, NewClientEventArgs args)
        {   
            logger.Info("New Client connected for host [{0}]", Configuration.Name);
            PsmSession newClient = new PsmSession(this, args.ClientTransport);
            newClient.SessionClosed += new EventHandler<SessionClosedEventArgs>((o,e) => SessionClosedHandler(o,e));
            AddClientSession(newClient);
            newClient.StartProcessing();
        }

        private void SessionClosedHandler(object sender, SessionClosedEventArgs args)
        {
            RemoveClientSession((PsmSession)sender);
            logger.Info("Client disconnected for host [{0}]", Configuration.Name);
        }

        private void AddClientSession(PsmSession clientSession)
        {
            lock (clientSessions)
            {
                clientSessions.Add(clientSession);
            }
        }

        private void RemoveClientSession(PsmSession clientSession)
        {
            lock (clientSessions)
            {
                clientSessions.Remove(clientSession);
            }
        }
    }
}
